#include <QMessageBox>

#include "../../datamanager/reg3volumedatanode.h"
#include "../../datamanager/geometrydatanode.h"
#include "../../mainwindow.h"
#include "../../contree/augmentedctree.h"
#include "../../contree/ctreecontourextractor.h"
#include "contreeplugin.h"
#include "contourcontrol.h"

using namespace PBVP;

ConTreePlugin::ConTreePlugin()
{
	m_IsoVal = 1.5;
	m_pControl = new ContourControl(this);
}

ConTreePlugin::~ConTreePlugin()
{
	delete m_pControl;
}

void ConTreePlugin::initialize(MainInterface* mainInterface)
{
	ToolPlugin::initialize(mainInterface);

	m_pDataManager = m_pMainInterface->getDataManager();
	contourAction = new QAction(tr("Construct Contour with CTree"), m_pMainInterface->getMainWindow());
	contourAction->setStatusTip(description());
	connect(contourAction, SIGNAL(triggered()), this, SLOT(extractContour()));
}

bool ConTreePlugin::isSupported(DataNode* pNode)
{
	// It supports volumetric data
#ifdef __GNU__
	if(pNode->data()->getDataSetType() == VOLUME_DATA) return true;
#else
	Reg3DVolumeDataNode *pVolNode = dynamic_cast<Reg3DVolumeDataNode *>(pNode);
	if(pVolNode) return true;
#endif
	return false;
}

//////////////////////////////////////////////////////////////////////////
// Public Slots
//////////////////////////////////////////////////////////////////////////

void ConTreePlugin::extractContour()
{
	if(m_pControl->exec()) {
		DataNode *pNode = m_pDataManager->getCurrentNode();
		if (!pNode)
		{
			QMessageBox::critical(m_pMainInterface->getMainWindow(), "Error",
				"No Data Selected in DataManager");
			return;
		}
		if(!isSupported(pNode)) {
			QMessageBox::critical(m_pMainInterface->getMainWindow(), "Error",
				"The input must be volumetric data");
			return;
		}

#ifdef __GNU__
		Reg3DVolumeDataNode *pVolNode = (Reg3DVolumeDataNode*)(pNode);
#else
		Reg3DVolumeDataNode *pVolNode = dynamic_cast<Reg3DVolumeDataNode*>(pNode);
		assert(pVolNode);
#endif

		Reg3DVolumeData *pVolData = (Reg3DVolumeData*)(pVolNode->data());
		QString cTreeName = pVolNode->getName().append(".ctr");
		AugmentedContourTree *pACTree = new AugmentedContourTree;
		if (!pACTree->loadFile(cTreeName.toAscii().data()))
		{
			if (QMessageBox::warning(m_pMainInterface->getMainWindow(), "Warning",
				"Recomputing Contour Tree is memory intensive (minimum 1GB required. 2GB recommended)\n Are you sure to continue?",
				QMessageBox::Ok|QMessageBox::Cancel)
				!= QMessageBox::Ok) {
					delete pACTree;
					return;
			}
			ConTreeConstructorReg3D *construcCT = new ConTreeConstructorReg3D(pVolData);
			delete pACTree;
			pACTree = construcCT->getAugmentedContourTree();
			pACTree->saveFile(cTreeName.toAscii().data());
			delete construcCT;
		}
		CTreeContourExtractor* pConExtractor = new CTreeContourExtractor(pVolData, pACTree);
		//GeometryData *pIsoSurf = pConExtractor->extractContour(pVolData, m_IsoVal);
		std::vector<GeometryData *> contours;
		m_IsoVal = m_pControl->getIsoValue();
		int nCon = m_pControl->numOfContours();
		int inner = m_pControl->innerRegion();
		pConExtractor->setInnerRegion(inner);
		int nc = pConExtractor->extractLargestContours(m_IsoVal, contours, nCon);
		delete pConExtractor;
		delete pACTree;

		for(int i = 0; i < nc; i++) {
			GeometryData *pIsoSurf = contours[i];
			GeometryDataNode *pGeoNode = new GeometryDataNode(pIsoSurf, m_pMainInterface);
			QString name = pNode->getName().append("_isosurf").append(QString::number(m_IsoVal));
			name.append("_").append(QString::number(i));
			pGeoNode->setName(name);
			//m_pRenderManager->setDefaultRenderer(pGeoNode);
			m_pDataManager->addDataNode(pGeoNode);
		}
		return;
	}
}

Q_EXPORT_PLUGIN2(contree, ConTreePlugin)
